//----------------------------------------------------------------------------
// mon.cpp
//
// clipboard monitor stuff
//
// Copyright (C) 2011 Neil Butterworth
//----------------------------------------------------------------------------

#include <cstring>
#include <iostream>
#include "mon.h"
#include "util.h"

static bool Verbose = false;

//----------------------------------------------------------------------------
// Create monitor from command line params
//----------------------------------------------------------------------------

ClipboardMonitor :: ClipboardMonitor( CmdLine & , bool verbose ) : mWnd( 0 ) {
	Verbose = verbose;
}

//----------------------------------------------------------------------------
// Start monitor. We register an invisible window, add it to the clipboard
// chain, and then spin a message loop waiting for clipboard changes.
//----------------------------------------------------------------------------

void ClipboardMonitor :: Start() {
	CreateMonWindow();
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

}

//----------------------------------------------------------------------------
// windows procedure for our invisible window
//----------------------------------------------------------------------------

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND nextview;
	//std::cout << "got message " << message << "\n";

	switch (message)
	{
		case WM_CREATE:
    		nextview = SetClipboardViewer( hWnd );
			break;

		case WM_CHANGECBCHAIN:
			if ((HWND) wParam == nextview ) {
				nextview  = (HWND) lParam;
			}
			else if ( nextview  != NULL) {
				SendMessage( nextview, message, wParam, lParam );
			}
    		break;

   		case WM_DRAWCLIPBOARD:  // clipboard contents changed.
			{
				static bool start = true;
				if ( start ) {
					start = false;
					std::cout << "Monitoring clipboard. Type Ctrl-C to quit." << std::endl;
					std::cout << "----- Current Contents -----\n";
				}
				else {
					std::cout << "----- Contents Changed -----\n";
				}
				Clipboard clip;
				UINT f = 0;
				bool showunk = true;
				while( (f = ::EnumClipboardFormats( f )) != 0 ) {
					if ( showunk || KnownFormat( f ) ) {
						std::cout << CFToStr( f ) << "\n";
					}
				}
				if ( Verbose && HasFormat( CF_TEXT ) ) {
					std::cout << "----------------------------\n";
					std::cout << GetTextData() << std::endl;
				}
			}
            SendMessage( nextview, message, wParam, lParam );
            break;

		case WM_DESTROY:
			ChangeClipboardChain( hWnd, nextview );
			PostQuitMessage(0);
			break;

		default:
			return DefWindowProc( hWnd, message, wParam, lParam );
	}
	return 0;
}

//----------------------------------------------------------------------------
// Create invisible monitoring window
//----------------------------------------------------------------------------

void ClipboardMonitor :: CreateMonWindow() {

	WNDCLASSEX wc;
	memset( &wc, 0, sizeof(wc) );

	HINSTANCE inst = GetModuleHandle( NULL );

	wc.cbSize = sizeof(wc);
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = inst;
	wc.lpszMenuName = NULL;
	wc.lpszClassName = "NCLIPMON";
	wc.hIconSm = NULL;

	if ( ! RegisterClassEx( &wc ) ) {
		throw ClipError( "Cannot register class for clipboard monitor window" );
	}

	mWnd = CreateWindow("NCLIPMON", "Hello", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, inst, NULL);

	if ( mWnd == 0 ) {
		throw ClipError( "Cannot create monitor window" );
	}
}

// end

